home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Meeting Pearls 4
/
Meeting Pearls Vol. IV (1996)(GTI - Schatztruhe)[!].iso
/
Pearls
/
dev
/
Oberon
/
OberonV4
/
system
/
Find.Mod
(
.txt
)
< prev
next >
Wrap
Oberon Text
|
1994-08-28
|
7KB
|
196 lines
Syntax10.Scn.Fnt
StampElems
Alloc
28 Aug 94
FoldElems
Syntax10i.Scn.Fnt
Syntax10b.Scn.Fnt
MODULE Find; (* HM
(*--------------------------------------------------------------------------
Find.Domain ~
Specify the files in which Find.All should search for a pattern.
Find.All ^
Searches the selection in the files specified with Find.Domain.
Lists all lines containing the pattern.
Find.Diff ^
Compares two texts starting from the two most recent selections
Sets new selections at the first position where the two texts differ.
--------------------------------------------------------------------------*)
IMPORT Display, Files, Oberon, Viewers, MenuViewers, TextFrames, Texts;
CONST
stdMenu = "System.Close System.Copy System.Grow Edit.Search Edit.Store ";
File = POINTER TO FileDesc;
FileDesc = RECORD
name: ARRAY 32 OF CHAR;
next: File
END;
file: File;
w: Texts.Writer;
out: Texts.Text;
PROCEDURE ScanPar (VAR s: Texts.Scanner);
VAR v: Viewers.Viewer; t: Texts.Text; beg, end, time: LONGINT;
BEGIN
Texts.OpenScanner(s, Oberon.Par.text, Oberon.Par.pos); Texts.Scan(s);
IF (s.class = Texts.Char) & (s.c = "^") THEN
Oberon.GetSelection(t, beg, end, time);
IF time >= 0 THEN
Texts.OpenScanner(s, t, beg); Texts.Scan(s)
END
END ScanPar;
PROCEDURE OpenViewer(name: ARRAY OF CHAR; t: Texts.Text);
VAR v: MenuViewers.Viewer; x, y: INTEGER; t1: Texts.Text; menu: TextFrames.Frame; buf: Texts.Buffer;
BEGIN
IF Files.Old("Edit.Menu.Text") = NIL THEN menu := TextFrames.NewMenu(name, stdMenu)
ELSE menu := TextFrames.NewMenu(name, "");
NEW(t1); Texts.Open(t1, "Edit.Menu.Text");
NEW(buf); Texts.OpenBuf(buf); Texts.Save(t1, 0, t1.len, buf); Texts.Append(menu.text, buf)
END;
Oberon.AllocateUserViewer(0, x, y);
v := MenuViewers.New(menu, TextFrames.NewText(t, 0), TextFrames.menuH, x, y)
END OpenViewer;
PROCEDURE Search (fn: ARRAY OF CHAR; pat: ARRAY OF CHAR; m: INTEGER);
CONST
bufSize = 31744; (*2**15 - 1024*)
CR = 0DX; TAB = 09X;
textTag = 496; oldTextTag = -4095;
f: Files.File; r: Files.Rider;
n, pos: LONGINT;
i, j, i0: INTEGER;
ch, patj: CHAR;
found: BOOLEAN;
tab: ARRAY 265 OF SHORTINT;
text: ARRAY bufSize OF CHAR;
BEGIN
(*----- open file *)
f := Files.Old(fn);
IF f = NIL THEN RETURN END;
Files.Set(r, f, 0); Files.ReadInt(r, i);
IF (i = textTag) OR (i = oldTextTag) THEN
pos := 0; (*Files.ReadLInt(r, pos); -- modified to search also in collapsed Fold segments*)
(*----- initialize tab *)
Texts.WriteString(w, "--- "); Texts.WriteString(w, fn); Texts.WriteLn(w);
FOR i := 0 TO 255 DO tab[i] := SHORT(m) END;
FOR i := 0 TO m-2 DO tab[ORD(pat[i])] := SHORT(m - i - 1) END;
patj := pat[m-1]; found := FALSE;
LOOP
(*----- read text[0..n-1] *)
n := Files.Length(f) - pos;
IF n > bufSize THEN n := bufSize END;
IF n < m THEN EXIT END;
Files.Set(r, f, pos); Files.ReadBytes(r, text, n);
(*----- search pat in text[0..n-1] *)
i := m - 1; j := i;
WHILE i < n DO
IF text[i] = patj THEN i0 := i;
REPEAT DEC(i); DEC(j) UNTIL (j < 0) OR (text[i] # pat[j]);
IF j < 0 THEN
(*------ found: print result *)
found := TRUE;
WHILE (i >= 0) & (text[i] # CR) & (text[i] >= TAB) DO DEC(i) END;
INC(i);
Files.Set(r, f, pos + i);
REPEAT Files.Read(r, ch); Texts.Write(w, ch); INC(i) UNTIL (ch = CR) OR (ch < TAB) OR (r.eof)
ELSE i := i + tab[ORD(text[i])]
END;
IF i <= i0 THEN i := i0 + 1 END;
j := m - 1
ELSE i := i + tab[ORD(text[i])]
END
END;
pos := pos + i - m + 1
END;
IF found THEN Texts.WriteLn(w); Texts.Append(out, w.buf) ELSE Texts.OpenWriter(w) END
ELSE
Texts.WriteString(w, fn); Texts.WriteString(w, " is no text file"); Texts.WriteLn(w);
Texts.Append(Oberon.Log, w.buf)
END Search;
(* -- commands -- *)
PROCEDURE Domain*; (* {filename} ~ *)
VAR s: Texts.Scanner; f, last: File;
BEGIN file := NIL; last := NIL;
ScanPar(s);
WHILE s.class = Texts.Name DO
NEW(f); f.next := NIL;
IF last = NIL THEN file := f ELSE last.next := f END;
last := f;
COPY(s.s, f.name);
Texts.Scan(s);
WHILE (s.class = Texts.Char) & (s.c = "/") DO Texts.Scan(s); Texts.Scan(s) END
END Domain;
PROCEDURE All*; (* ^ *)
VAR pat: ARRAY 128 OF CHAR; m: INTEGER; f: File;
PROCEDURE ReadPattern (VAR pat: ARRAY OF CHAR; VAR m: INTEGER);
VAR t: Texts.Text; r: Texts.Reader; beg, end, time: LONGINT; ch: CHAR;
BEGIN
Oberon.GetSelection(t, beg, end, time);
IF time > 0 THEN
Texts.OpenReader(r, t, beg); m := 0;
WHILE beg < end DO Texts.Read(r, ch);
IF m < 127 THEN pat[m] := ch END;
INC(m); INC(beg)
END;
pat[m] := 0X
END;
END ReadPattern;
BEGIN
ReadPattern(pat, m);
out := TextFrames.Text("");
OpenViewer(pat, out); f := file;
WHILE f # NIL DO
Search(f.name, pat, m);
f := f.next
END All;
PROCEDURE Diff*; (*- compares two texts from the last two selections; sets selection to first difference *)
VAR f1, f2: TextFrames.Frame; p1, p2: LONGINT; r1, r2: Texts.Reader; ch1, ch2: CHAR;
PROCEDURE GetSelection(VAR F: TextFrames.Frame; VAR pos: LONGINT);
VAR time: LONGINT; v: Viewers.Viewer; x: INTEGER; f: Display.Frame;
BEGIN
time := -1; x := 0; F := NIL;
WHILE x < Display.Width DO
v := Viewers.This(x, 0);
WHILE v.state > 1 DO
f := v.dsc.next;
WITH f: TextFrames.Frame DO
IF f.hasSel & (f.time > time) THEN F := f; pos := f.selbeg.pos; time := f.time END
ELSE
END;
v := Viewers.Next(v)
END;
x := x + v.W
END;
IF F # NIL THEN TextFrames.RemoveSelection(F); TextFrames.RemoveCaret(F) END
END GetSelection;
PROCEDURE ShowSelection(f: TextFrames.Frame; pos: LONGINT);
VAR x: LONGINT;
BEGIN
IF pos > TextFrames.Pos(f, f.X + f.W - 1, f.Y) THEN
x := pos - 150; IF x < 0 THEN x := 0 END;
TextFrames.Show(f, x)
END;
TextFrames.SetSelection(f, pos, pos+1)
END ShowSelection;
BEGIN
GetSelection(f1, p1); GetSelection(f2, p2);
IF (f1 # NIL) & (f2 # NIL) THEN
Texts.OpenReader(r1, f1.text, p1);
Texts.OpenReader(r2, f2.text, p2);
REPEAT
Texts.Read(r1, ch1); INC(p1); Texts.Read(r2, ch2); INC(p2);
UNTIL (ch1 # ch2) OR (ch1 = 0X);
IF (ch1 = 0X) OR (ch2 = 0X) THEN DEC(p1); DEC(p2) END;
ShowSelection(f1, p1-1); ShowSelection(f2, p2-1)
END Diff;
BEGIN
file := NIL; Texts.OpenWriter(w)
END Find.
(*--------------------------------------------------------------------------
Find.Domain ~
Specify the files in which Find.All should search for a pattern.
Find.All ^
Searches the selection in the files specified with Find.Domain.
Lists all lines containing the pattern.
Find.Diff ^
Compares two texts starting from the two most recent selections
Sets new selections at the first position where the two texts differ.
--------------------------------------------------------------------------*)